＃！/ usr / bin / php
<？php

使用splitbrain \ phpcli \ CLI;
使用splitbrain \ phpcli \ Options;

if（！defined（'DOKU_INC'））define（'DOKU_INC'，realpath（dirname（__ FILE__）。'/../'）。'/'）;
define（'NOSESSION'，1）;
require_once（DOKU_INC。'inc / init.php'）;

/ **
 *轻松管理DokuWiki git存储库
 *
 * @作者Andreas Gohr <andi@splitbrain.org>
 * /
GitToolCLI类扩展了CLI {

    / **
     *在给定的$ options对象上注册选项和参数
     *
     * @param选项$ options
     * @返回无效
     * /
    受保护的功能设置（选项$ options）{
        $ options-> setHelp（
            “管理DokuWiki及其插件和模板的git存储库。\ n \ n”。
            “ $> ./bin/gittool.php克隆库模板：ach \ n”。
            “ $> ./bin/gittool.php仓库\ n”。
            “ $> ./bin/gittool.php origin -v”
        ）;

        $ options-> registerArgument（
            '命令'，
            '执行命令。见下文'，
            真正
        ）;

        $ options-> registerCommand（
            '克隆'，
            '尝试通过git安装已知的插件或模板（带有模板的前缀：）。使用DokuWiki.org'。
            '插件存储库以找到正确的git存储库。可以将多个扩展名作为参数给出
        ）;
        $ options-> registerArgument（
            '延期'，
            '要安装的扩展名，以\'template：\'为模板的前缀，'
            真正，
            '克隆'
        ）;

        $ options-> registerCommand（
            '安装'，
            '与clone相同，但是当找不到git源存储库时，将通过'安装扩展。
            '下载'
        ）;
        $ options-> registerArgument（
            '延期'，
            '要安装的扩展名，以\'template：\'为模板的前缀，'
            真正，
            '安装'
        ）;

        $ options-> registerCommand（
            “回购”，
            “列出在此DokuWiki安装中找到的所有git存储库”
        ）;

        $ options-> registerCommand（
            '*'，
            “假定所有未知命令都是git的参数，并将在所有存储库中执行”。
            “在此DokuWiki安装中找到”
        ）;
    }

    / **
     *您的主程序
     *
     *参数和选项已在运行时解析
     *
     * @param选项$ options
     * @返回无效
     * /
    受保护的函数main（Options $ options）{
        $ command = $ options-> getCmd（）;
        $ args = $ options-> getArgs（）;
        if（！$ command）$ command = array_shift（$ args）;

        开关（$命令）{
            案件 ''：
                echo $ options-> help（）;
                打破;
            案例“克隆”：
                $ this-> cmd_clone（$ args）;
                打破;
            案例“安装”：
                $ this-> cmd_install（$ args）;
                打破;
            案例“回购”：
            案例“回购”：
                $ this-> cmd_repos（）;
                打破;
            默认：
                $ this-> cmd_git（$ command，$ args）;
        }
    }

    / **
     *尝试使用git clone安装给定的扩展
     *
     * @参数数组$ extensions
     * /
    公共功能cmd_clone（$ extensions）{
        $错误= array（）;
        $ succeeded = array（）;

        foreach（$ extensions as $ ext）{
            $ repo = $ this-> getSourceRepo（$ ext）;

            if（！$ repo）{
                $ this-> error（“找不到$ ext的存储库”）;
                $ errors [] = $ ext;
            }其他{
                if（$ this-> cloneExtension（$ ext，$ repo））{
                    $ succeeded [] = $ ext;
                }其他{
                    $ errors [] = $ ext;
                }
            }
        }

        回显“ \ n”；
        if（$ succeeded）$ this-> success（'成功克隆了以下扩展名：'。join（'，'，$ succeeded））;
        if（$ errors）$ this-> error（'无法克隆以下扩展名：'。join（'，'，$ errors））;
    }

    / **
     *尝试使用带有fallback的git clone安装给定的扩展
     *
     * @参数数组$ extensions
     * /
    公共功能cmd_install（$ extensions）{
        $错误= array（）;
        $ succeeded = array（）;

        foreach（$ extensions as $ ext）{
            $ repo = $ this-> getSourceRepo（$ ext）;

            if（！$ repo）{
                $ this-> info（“找不到$ ext的存储库”）;
                if（$ this-> downloadExtension（$ ext））{
                    $ succeeded [] = $ ext;
                }其他{
                    $ errors [] = $ ext;
                }
            }其他{
                if（$ this-> cloneExtension（$ ext，$ repo））{
                    $ succeeded [] = $ ext;
                }其他{
                    $ errors [] = $ ext;
                }
            }
        }

        回显“ \ n”；
        if（$ succeeded）$ this-> success（'成功安装了以下扩展名：'。join（'，'，$ succeeded））;
        if（$ errors）$ this-> error（'无法安装以下扩展名：'。join（'，'，$ errors））;
    }

    / **
     *在每个存储库中执行给定的git命令
     *
     * @参数$ cmd
     * @参数$ arg
     * /
    公共功能cmd_git（$ cmd，$ arg）{
        $ repos = $ this-> findRepos（）;

        $ shell = array_merge（array（'git'，$ cmd），$ arg）;
        $ shell = array_map（'escapeshellarg'，$ shell）;
        $ shell = join（''，$ shell）;

        foreach（$ repos as $ repo）{
            if（！@ chdir（$ repo））{
                $ this-> error（“无法更改为$ repo”）;
                继续;
            }

            $ this-> info（“在$ repo中执行$ shell”）;
            $ ret = 0;
            系统（$ shell，$ ret）;

            if（$ ret == 0）{
                $ this-> success（“ git成功完成$ repo”）;
            }其他{
                $ this-> error（“ git在$ repo中失败”）;
            }
        }
    }

    / **
     *仅列出存储库
     * /
    公共功能cmd_repos（）{
        $ repos = $ this-> findRepos（）;
        foreach（$ repos as $ repo）{
            回显“ $ repo \ n”；
        }
    }

    / **
     *从给定的下载URL安装扩展
     *
     * @参数字符串$ ext
     * @return bool | null
     * /
    私有函数downloadExtension（$ ext）{
        / ** @var helper_plugin_extension_extension $ plugin * /
        $ plugin = plugin_load（'helper'，'extension_extension'）;
        if（！$ ext）die（“扩展插件不可用，无法继续”）;

        $ plugin-> setExtension（$ ext）;

        $ url = $ plugin-> getDownloadURL（）;
        if（！$ url）{
            $ this-> error（“ $ ext没有下载URL”）;
            返回false；
        }

        $ ok = false;
        尝试{
            $ this-> info（“通过从$ url下载安装$ ext”）；
            $ ok = $ plugin-> installFromURL（$ url）;
        } catch（Exception $ e）{
            $ this-> error（$ e-> getMessage（））;
        }

        if（$ ok）{
            $ this-> success（“通过下载安装$ ext”）；
            返回true；
        }其他{
            $ this-> success（“无法通过下载安装$ ext”）；
            返回false；
        }
    }

    / **
     *从给定的存储库中克隆扩展名
     *
     * @参数字符串$ ext
     * @参数字符串$ repo
     * @返回布尔
     * /
    私有函数cloneExtension（$ ext，$ repo）{
        if（substr（$ ext，0，9）=='模板：'）{
            $ target = fullpath（tpl_incdir（）。'../'。substr（$ ext，9））;
        }其他{
            $ target = DOKU_PLUGIN。$ ext;
        }

        $ this-> info（“将$ ext从$ repo克隆到$ target”）;
        $ ret = 0;
        system（“ git clone $ repo $ target”，$ ret）;
        if（$ ret === 0）{
            $ this-> success（“ $ ext的克隆成功”）;
            返回true；
        }其他{
            $ this-> error（“克隆$ ext失败”）;
            返回false；
        }
    }

    / **
     *返回此DokuWiki安装中的所有git存储库
     *
     *仅在根目录，模板目录和插件目录中查找。
     *
     * @返回数组
     * /
    私有函数findRepos（）{
        $ this-> info（'寻找.git目录'）;
        $数据= array_merge（
            glob（DOKU_INC。'.git'，GLOB_ONLYDIR），
            glob（DOKU_PLUGIN。'* /。git'，GLOB_ONLYDIR），
            glob（fullpath（tpl_incdir（）。'../'）。'/*/.git'，GLOB_ONLYDIR）
        ）;

        if（！$ data）{
            $ this-> error（'没有找到.git目录'）;
        }其他{
            $ this-> success（'Found'。count（$ data）。'.git directory'）;
        }
        $ data = array_map（'fullpath'，array_map（'dirname'，$ data））;
        返回$ data;
    }

    / **
     *返回给定扩展名的存储库
     *
     * @param $扩展名
     * @return false |字符串
     * /
    私有函数getSourceRepo（$ extension）{
        / ** @var helper_plugin_extension_extension $ ext * /
        $ ext = plugin_load（'helper'，'extension_extension'）;
        if（！$ ext）die（“扩展插件不可用，无法继续”）;

        $ ext-> setExtension（$ extension）;

        $ repourl = $ ext-> getSourcerepoURL（）;
        if（！$ repourl）返回false;

        //匹配github仓库
        if（preg_match（'/ github \ .com \ /（[[^ \ /] +）\ /（[^ \ /] +）/ i'，$ repourl，$ m））{
            $ user = $ m [1];
            $ repo = $ m [2];
            返回'https://github.com/'。$ user。'/' $ repo。'.git';
        }

        //匹配奇妙的仓库
        if（preg_match（'/ gitorious.org \ /（[^ \ /] +）\ /（[^ \ /] +）？/ i'，$ repourl，$ m））{
            $ user = $ m [1];
            $ repo = $ m [2];
            if（！$ repo）$ repo = $ user;

            返回'https://git.gitorious.org/'。$ user。'/' $ repo。'.git';
        }

        //匹配bitbucket存储库-尽管大多数人还是在这里使用水银
        if（preg_match（'/ bitbucket \ .org \ /（[^ \ /] +）\ /（[^ \ /] +）/ i'，$ repourl，$ m））{
            $ user = $ m [1];
            $ repo = $ m [2];
            返回'https://bitbucket.org/'。$ user。'/' $ repo。'.git';
        }

        返回false；
    }
}

//主
$ cli =新的GitToolCLI（）;
$ cli-> run（）;